/*
- Read and write Coto files.
+ Read and write cotoGPS files.
- Copyright (C) 2005 Tobias Minich, robertlipe@usa.net
+ Copyright (C) 2005 Tobias Minich,
Based on the Cetus I/O Filter,
Copyright (C) 2002 Robert Lipe, robertlipe@usa.net
#include "coldsync/pdb.h"
#define MYNAME "cotoGPS"
+
#define MYTYPETRACK 0x5452434b /* TRCK */
#define MYTYPEWPT 0x44415441 /* DATA */
-#define MYCREATOR 0x636f4750 /* coGP */
+#define MYCREATOR 0x636f4750 /* coGP */
#define NOTESZ 4096
#define DESCSZ 4096
+#define MAX_MARKER_NAME_LENGTH 20
+#define CATEGORY_NAME_LENGTH 16
+
typedef enum {
- cotofixNone = 0, /* No Fix or Warning */
+ cotofixNone = 0, /* No Fix or Warning */
cotofixReserved = 1, /* Shouldn't occur*/
- cotofix2D = 2, /* retrieved from a GPS with a 2D fix */
- cotofix3D = 3, /* retrieved from a GPS with a 3D fix */
- cotofixDGPS = 4, /* retrieved from a GPS with a DGPS signal */
+ cotofix2D = 2, /* retrieved from a GPS with a 2D fix */
+ cotofix3D = 3, /* retrieved from a GPS with a 3D fix */
+ cotofixDGPS = 4, /* retrieved from a GPS with a DGPS signal */
} fix_quality;
struct record_track {
word alt; /* Altitude */
/* accuracy and precision information for use where applicable */
- uword hdop; /* _dop * 10 */
- uword vdop;
- uword pdop;
+ gbuint16 hdop; /* _dop * 10 */
+ gbuint16 vdop;
+ gbuint16 pdop;
ubyte sat_tracked;
ubyte fix_quality;
- uword speed; /* *10 */
- udword time; /* Palm Time */
+ gbuint16 speed; /* *10 */
+ gbuint32 time; /* Palm Time */
};
-#define MAX_MARKER_NAME_LENGTH 20
struct record_wpt {
char lon[8];
char lat[8];
char name[MAX_MARKER_NAME_LENGTH];
+ char notes[1];
};
typedef char appinfo_category[16];
-#define APPINFO_PACKED_SIZE sizeof(uword)+16*sizeof(appinfo_category)+17*sizeof(ubyte)
-struct appinfo {
- uword renamedCategories;
- appinfo_category categories[16];
+typedef struct appinfo {
+ ubyte U0;
+ ubyte renamedCategories;
+ appinfo_category categories[CATEGORY_NAME_LENGTH];
ubyte ids[16];
ubyte maxid;
-};
+} appinfo_t;
+
+#define APPINFO_SIZE sizeof(appinfo_t)
static FILE *file_in;
static FILE *file_out;
static const char *out_fname;
static const char *in_fname; /* We might need that for naming tracks */
static struct pdb *opdb;
+static short_handle mkshort_wr_handle;
-static char *trackname = NULL;
static char *zerocat = NULL;
static char *internals = NULL;
static
arglist_t coto_args[] = {
- {"trackname", &trackname, "Track name", NULL, ARGTYPE_STRING },
{"zerocat", &zerocat, "Name of the 'unassigned' category.", NULL, ARGTYPE_STRING },
- {"internals", &internals, "Export some internal stuff to notes.", NULL, ARGTYPE_STRING|ARGTYPE_HIDDEN },
+ {"internals", &internals, "Export some internal stuff to notes.", NULL, ARGTYPE_STRING | ARGTYPE_HIDDEN },
{0, 0, 0, 0, 0 }
};
rd_deinit(void)
{
fclose(file_in);
- if ( trackname ) {
- xfree(trackname);
- trackname = NULL;
- }
}
static void
wr_deinit(void)
{
fclose(file_out);
- if ( trackname ) {
- xfree(trackname);
- trackname = NULL;
+}
+
+/* helpers */
+
+static char *
+coto_get_icon_descr(int category, const appinfo_t *app)
+{
+ char buff[CATEGORY_NAME_LENGTH + 1] = "Not Assigned";
+ if ((category >= 0) && (category < 16))
+ {
+ if ((category > 0) && (app->categories[category][0] == '\0'))
+ category = 0;
+
+ strncpy(buff, app->categories[category], sizeof(buff) - 1);
+ if (buff[0] == '\0')
+ return NULL;
}
+ return xstrdup(buff);
}
static void
struct record_track *rec;
struct pdb_record *pdb_rec;
route_head *trk_head;
- char *loctrackname = NULL;
+ char *track_name;
- if (trackname)
- // Given by user
- loctrackname = xstrdup(trackname);
- else if (strncmp(pdb->name, "cotoGPS TrackDB", PDB_DBNAMELEN))
+ if (strncmp(pdb->name, "cotoGPS TrackDB", PDB_DBNAMELEN) != 0)
// Use database name if not default
- loctrackname = xstrndup(pdb->name, PDB_DBNAMELEN);
+ track_name = xstrndup(pdb->name, PDB_DBNAMELEN);
else {
- // Use filename
- const char *fnametmp = strrchr(in_fname, '/'); // FIXME: Don't know if this works on Windows
+ // Use filename for new track title
+ const char *fnametmp = strrchr(in_fname, '/');
+ if (fnametmp == NULL)
+ fnametmp = strrchr(in_fname, '\\');
if (fnametmp)
fnametmp++;
else
fnametmp = in_fname;
- loctrackname = xstrndup(fnametmp, strrchr(fnametmp,'.')-fnametmp);
+ if (strrchr(fnametmp, '.') != NULL)
+ track_name = xstrndup(fnametmp, strrchr(fnametmp,'.') - fnametmp);
+ else
+ track_name = xstrdup(fnametmp);
}
trk_head = route_head_alloc();
track_add_head(trk_head);
- trk_head->rte_name = loctrackname;
+ trk_head->rte_name = track_name;
- for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) {
+ for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next)
+ {
waypoint *wpt_tmp;
wpt_tmp = waypt_new();
rec = (struct record_track *) pdb_rec->data;
-
+
wpt_tmp->longitude = -pdb_read_double(&rec->longitude)*360.0/(2.0*M_PI);
wpt_tmp->latitude = pdb_read_double(&rec->latitude)*360.0/(2.0*M_PI);
+
// It's not the course, so leave it out for now
// wpt_tmp->course = pdb_read_double(&rec->arc);
wpt_tmp->altitude = be_read16(&rec->alt);
- if (internals) {
+ if (internals)
+ {
// Parse the option as xcsv delimiter
const char *inter = xcsv_get_char_from_constant_table(internals);
char temp[256];
wpt_tmp->hdop = be_read16(&rec->hdop)/10.0;
wpt_tmp->vdop = be_read16(&rec->vdop)/10.0;
wpt_tmp->sat = rec->sat_tracked;
- switch (rec->fix_quality) {
- case cotofixNone: wpt_tmp->fix = fix_none; break;
- case cotofixReserved: wpt_tmp->fix = fix_unknown; break;
- case cotofix2D: wpt_tmp->fix = fix_2d; break;
- case cotofix3D: wpt_tmp->fix = fix_3d; break;
- case cotofixDGPS: wpt_tmp->fix = fix_dgps; break;
+ switch (rec->fix_quality)
+ {
+ case cotofixNone:
+ wpt_tmp->fix = fix_none;
+ break;
+ case cotofixReserved:
+ wpt_tmp->fix = fix_unknown;
+ break;
+ case cotofix2D:
+ wpt_tmp->fix = fix_2d;
+ break;
+ case cotofix3D:
+ wpt_tmp->fix = fix_3d;
+ break;
+ case cotofixDGPS:
+ wpt_tmp->fix = fix_dgps;
+ break;
}
wpt_tmp->speed = be_read16(&rec->speed)/10.0;
- wpt_tmp->creation_time = be_read32(&rec->time) - 2082844800U;
-
+ rec->time = be_read32(&rec->time);
+ if (rec->time != 0)
+ {
+ rec->time -= 2082844800U;
+ wpt_tmp->creation_time = rec->time;
+ }
route_add_wpt(trk_head, wpt_tmp);
-
}
-
}
static void
{
struct record_wpt *rec;
struct pdb_record *pdb_rec;
- char *vdata;
- struct appinfo *app;
-
+ appinfo_t *app;
app = (struct appinfo *) pdb->appinfo;
- for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next) {
+ for(pdb_rec = pdb->rec_index.rec; pdb_rec; pdb_rec=pdb_rec->next)
+ {
waypoint *wpt_tmp;
- int c=-1;
wpt_tmp = waypt_new();
rec = (struct record_wpt *) pdb_rec->data;
- // Find category
- /* I thought this would be the proper way. Leaving it in in case it becomes the proper one =)
- for(i=0;i<16;i++)
- if (app->ids[i] == pdb_rec->category) {c=i; break;}
- */
- c = pdb_rec->category;
-
wpt_tmp->longitude = -pdb_read_double(&rec->lon)*360.0/(2.0*M_PI);
wpt_tmp->latitude = pdb_read_double(&rec->lat)*360.0/(2.0*M_PI);
- wpt_tmp->shortname = xstrdup((char *) &rec->name);
- wpt_tmp->description = xstrdup((char *) &rec->name);
-
- if (c>0)
- wpt_tmp->icon_descr = xstrndup(app->categories[c], 16);
- else if (c<0)
- wpt_tmp->icon_descr = xstrdup("Unknown");
+ wpt_tmp->shortname = xstrndup(rec->name, sizeof(rec->name));
+
+ wpt_tmp->icon_descr = coto_get_icon_descr(pdb_rec->category, app);
if (wpt_tmp->icon_descr)
wpt_tmp->wpt_flags.icon_descr_is_dynamic = 1;
- if (pdb_rec->data_len>sizeof(*rec)) {
- vdata = (char *) pdb_rec->data + sizeof(*rec);
- wpt_tmp->notes = xstrdup(vdata);
- }
+ wpt_tmp->notes = xstrdup(rec->notes);
waypt_add(wpt_tmp);
}
fatal(MYNAME ": Not a cotoGPS file.\n");
}
- if (pdb->version > 0) {
- fatal(MYNAME ": This file is from an unsupported newer version of cotoGPS. It may be supported in a newer version of GPSBabel.\n");
- }
+ is_fatal((pdb->version > 0),
+ MYNAME ": This file is from an unsupported newer version of cotoGPS. It may be supported in a newer version of GPSBabel.\n");
- if (pdb->type == MYTYPETRACK)
- coto_track_read(pdb);
- if (pdb->type == MYTYPEWPT)
- coto_wpt_read(pdb);
+ switch(pdb->type)
+ {
+ case MYTYPETRACK:
+ coto_track_read(pdb);
+ break;
+ case MYTYPEWPT:
+ coto_wpt_read(pdb);
+ break;
+ }
free_pdb(pdb);
}
strncpy(opdb->name, "cotoGPS MarkerDB", PDB_DBNAMELEN);
- opdb->appinfo_len = APPINFO_PACKED_SIZE;
- opdb->appinfo = calloc(APPINFO_PACKED_SIZE,1);
+ opdb->appinfo_len = APPINFO_SIZE;
+ opdb->appinfo = calloc(APPINFO_SIZE,1);
ai = (struct appinfo *) opdb->appinfo;
be_write16(&ai->renamedCategories, 31); // Don't ask me why...
struct appinfo *ai = (struct appinfo *) opdb->appinfo;
static int ct;
struct pdb_record *opdb_rec;
- static short_handle mkshort_wr_handle;
char *notes = NULL;
char *shortname = NULL;
- char *vdata;
- int size = sizeof(*rec);
+ int size;
ubyte cat = 0;
int i;
setshort_length(mkshort_wr_handle, MAX_MARKER_NAME_LENGTH);
setshort_whitespace_ok(mkshort_wr_handle, 1);
- if ((global_opts.synthesize_shortnames && wpt->description) || (!wpt->shortname))
+ if ((global_opts.synthesize_shortnames && wpt->description) || (wpt->shortname == NULL))
shortname = mkshort_from_wpt(mkshort_wr_handle, wpt);
else
shortname = xstrdup(wpt->shortname);
- if ((wpt->description) && ((strlen(wpt->description) > MAX_MARKER_NAME_LENGTH) || (strcmp(wpt->description, wpt->shortname)))) {
- if ((wpt->notes) && (strcmp(wpt->description, wpt->notes))) {
- size+=strlen(wpt->description)+strlen(wpt->notes)+9;
- notes = xcalloc(strlen(wpt->description)+strlen(wpt->notes)+9,1);
- sprintf(notes,"%s\nNotes:\n%s", wpt->description, wpt->notes);
+ if ((wpt->description) && ((strlen(wpt->description) > MAX_MARKER_NAME_LENGTH) || (strcmp(wpt->description, wpt->shortname))))
+ {
+ if ((wpt->notes) && (strcmp(wpt->description, wpt->notes) != 0))
+ {
+ notes = xcalloc(strlen(wpt->description) + strlen(wpt->notes) + 9, 1);
+ sprintf(notes, "%s\nNotes:\n%s", wpt->description, wpt->notes);
} else {
- size+=strlen(wpt->description)+1;
notes = xstrdup(wpt->description);
}
- } else if (wpt->notes) {
- size+=strlen(wpt->notes)+1;
+ }
+ else if (wpt->notes != NULL)
+ {
notes = xstrdup(wpt->notes);
}
- rec = xcalloc(size,1);
+ if (notes != NULL)
+ size += strlen(notes);
+ rec = xcalloc(size, 1);
+
pdb_write_double(&rec->lon, -2.0*M_PI*wpt->longitude/360.0);
pdb_write_double(&rec->lat, 2.0*M_PI*wpt->latitude/360.0);
- snprintf((char *) &rec->name, MAX_MARKER_NAME_LENGTH, "%s", shortname);
+ strncpy(rec->name, shortname, MAX_MARKER_NAME_LENGTH);
- if (notes) {
- vdata = (char *) rec + sizeof(*rec);
- strcpy(vdata, notes);
+ if (notes)
+ {
+ strcpy(rec->notes, notes);
xfree(notes);
}
- if (wpt->icon_descr) {
- for(i=1;i<16;i++)
+ if (wpt->icon_descr)
+ {
+ for(i = 1; i < 16; i++)
if (!strncmp(wpt->icon_descr, ai->categories[i], 16)) {cat=i; break;}
if (!cat) {
// We have a new one
if (ai->maxid<15) {
i = ++ai->maxid;
snprintf(ai->categories[i], 16, "%s", wpt->icon_descr);
- cat=ai->ids[i]=i;
+ cat = ai->ids[i] = i;
} else {
// We're full!
warning(MYNAME ": Categories full. Category '%s' written as %s.\n", wpt->icon_descr, zerocat?zerocat:"Not Assigned");
opdb_rec = new_Record (0, cat, ct++, size, (const ubyte *)rec);
- if (opdb_rec == NULL) {
+ if (opdb_rec == NULL)
fatal(MYNAME ": libpdb couldn't create record\n");
- }
- if (pdb_AppendRecord(opdb, opdb_rec)) {
+ if (pdb_AppendRecord(opdb, opdb_rec))
fatal(MYNAME ": libpdb couldn't append record\n");
- }
+
xfree(shortname);
xfree(rec);
mkshort_del_handle(&mkshort_wr_handle);
-
}
static void
}
coto_prepare_wpt_write(opdb);
+
waypt_disp_all(coto_wpt_write);
+ /*
+ if we want waypoints from all data, we should create a new filter for that
+
track_disp_all(NULL, NULL, coto_wpt_write);
route_disp_all(NULL, NULL, coto_wpt_write);
+ */
pdb_Write(opdb, fileno(file_out));